"""
查询处理器统一接口

整合查询清理、关键词提取和查询扩展功能。
"""

from typing import List, Dict, Optional, Any
from dataclasses import dataclass

from .cleaner import QueryCleaner
from .keywords import KeywordExtractor
from .expander import QueryExpander


@dataclass
class QueryProcessResult:
    """查询处理结果"""
    original_query: str
    cleaned_query: str
    keywords: List[str]
    expanded_query: str
    processing_time: float
    metadata: Dict[str, Any]


class QueryProcessor:
    """
    查询处理器

    整合查询清理、关键词提取和查询扩展功能，提供统一的查询处理接口。
    支持灵活的配置和处理策略。
    """

    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """
        初始化查询处理器

        Args:
            config: 处理器配置
        """
        self.config = config or {}

        # 初始化各个组件
        self.cleaner = QueryCleaner(self.config.get('cleaner', {}))
        self.keyword_extractor = KeywordExtractor(self.config.get('keywords', {}))
        self.expander = QueryExpander(self.config.get('expander', {}))

        # 默认处理选项
        self.default_options = {
            'enable_cleaning': True,
            'enable_keywords': True,
            'enable_expansion': False,
            'keyword_method': 'hybrid',
            'expansion_methods': ['synonyms', 'related'],
            'max_keywords': 10,
            'max_expansions': 5
        }
        self.default_options.update(self.config.get('options', {}))

    def process_query(
        self,
        query: str,
        options: Optional[Dict[str, Any]] = None
    ) -> QueryProcessResult:
        """
        处理单个查询

        Args:
            query: 原始查询
            options: 处理选项

        Returns:
            QueryProcessResult: 处理结果
        """
        import time

        start_time = time.time()

        # 合并选项
        process_options = self.default_options.copy()
        process_options.update(options or {})

        # 查询清理
        if process_options['enable_cleaning']:
            cleaned_query = self.cleaner.clean_query(query)
        else:
            cleaned_query = query

        # 关键词提取
        keywords = []
        if process_options['enable_keywords']:
            keywords = self.keyword_extractor.extract_keywords(
                cleaned_query,
                method=process_options['keyword_method'],
                max_keywords=process_options['max_keywords']
            )

        # 查询扩展
        expanded_query = cleaned_query
        expansion_info = {}
        if process_options['enable_expansion'] and keywords:
            expansion_result = self.expander.expand_query(
                cleaned_query,
                keywords=keywords,
                methods=process_options['expansion_methods'],
                max_expansions=process_options['max_expansions']
            )
            expanded_query = expansion_result['expanded_query']
            expansion_info = {
                'expansion_terms': expansion_result['expansion_terms'],
                'expansion_count': expansion_result['expansion_count'],
                'expansion_ratio': expansion_result['expansion_ratio']
            }

        processing_time = time.time() - start_time

        # 构建元数据
        metadata = {
            'options_used': process_options,
            'expansion_info': expansion_info,
            'query_stats': self._calculate_query_stats(query, cleaned_query, keywords)
        }

        return QueryProcessResult(
            original_query=query,
            cleaned_query=cleaned_query,
            keywords=keywords,
            expanded_query=expanded_query,
            processing_time=processing_time,
            metadata=metadata
        )

    def process_query_batch(
        self,
        queries: List[str],
        options: Optional[Dict[str, Any]] = None
    ) -> List[QueryProcessResult]:
        """
        批量处理查询

        Args:
            queries: 查询列表
            options: 处理选项

        Returns:
            List[QueryProcessResult]: 处理结果列表
        """
        results = []

        for query in queries:
            try:
                result = self.process_query(query, options)
                results.append(result)
            except Exception as e:
                # 创建错误结果
                error_result = QueryProcessResult(
                    original_query=query,
                    cleaned_query=query,
                    keywords=[],
                    expanded_query=query,
                    processing_time=0,
                    metadata={'error': str(e)}
                )
                results.append(error_result)

        return results

    def get_recommended_query(
        self,
        query: str,
        context: Optional[Dict[str, Any]] = None
    ) -> QueryProcessResult:
        """
        获取推荐的查询处理结果

        根据查询特征和上下文智能选择处理策略。

        Args:
            query: 原始查询
            context: 上下文信息

        Returns:
            QueryProcessResult: 推荐的处理结果
        """
        # 分析查询特征
        query_features = self._analyze_query_features(query)

        # 根据特征选择处理策略
        options = self._select_processing_strategy(query_features, context)

        return self.process_query(query, options)

    def _analyze_query_features(self, query: str) -> Dict[str, Any]:
        """分析查询特征"""
        import re

        features = {
            'length': len(query),
            'word_count': len(query.split()),
            'has_chinese': bool(re.search(r'[\u4e00-\u9fff]', query)),
            'has_english': bool(re.search(r'[a-zA-Z]', query)),
            'has_numbers': bool(re.search(r'\d', query)),
            'has_special_chars': bool(re.search(r'[^\w\s\u4e00-\u9fff]', query)),
            'question_indicators': bool(re.search(r'[？?什么|怎么|为什么|how|what|why]', query)),
            'is_complex': len(query) > 50
        }

        return features

    def _select_processing_strategy(
        self,
        features: Dict[str, Any],
        context: Optional[Dict[str, Any]]
    ) -> Dict[str, Any]:
        """选择处理策略"""
        options = self.default_options.copy()

        # 根据查询特征调整策略
        if features['is_complex']:
            # 复杂查询启用所有功能
            options['enable_expansion'] = True
            options['max_keywords'] = 15
            options['max_expansions'] = 8
        elif features['question_indicators']:
            # 问题查询启用扩展
            options['enable_expansion'] = True
            options['expansion_methods'] = ['synonyms']
        elif features['length'] < 10:
            # 短查询启用扩展
            options['enable_expansion'] = True
            options['expansion_methods'] = ['related']

        # 根据上下文调整
        if context:
            if context.get('domain') == 'technical':
                options['keyword_method'] = 'frequency'
            elif context.get('domain') == 'academic':
                options['keyword_method'] = 'hybrid'
                options['enable_expansion'] = True

            if context.get('precision_priority'):
                # 高精度要求：减少扩展，提高关键词质量
                options['max_expansions'] = 3
                options['max_keywords'] = 8
            elif context.get('recall_priority'):
                # 高召回要求：增加扩展
                options['max_expansions'] = 10
                options['expansion_methods'] = ['synonyms', 'related']

        return options

    def _calculate_query_stats(
        self,
        original: str,
        cleaned: str,
        keywords: List[str]
    ) -> Dict[str, Any]:
        """计算查询统计信息"""
        return {
            'original_length': len(original),
            'cleaned_length': len(cleaned),
            'length_reduction': (len(original) - len(cleaned)) / len(original) if original else 0,
            'keyword_count': len(keywords),
            'keyword_density': len(keywords) / len(cleaned.split()) if cleaned else 0,
            'avg_keyword_length': sum(len(k) for k in keywords) / len(keywords) if keywords else 0
        }

    def compare_processing_methods(
        self,
        query: str,
        methods_list: List[Dict[str, Any]]
    ) -> Dict[str, Any]:
        """
        比较不同处理方法的效果

        Args:
            query: 测试查询
            methods_list: 处理方法列表

        Returns:
            Dict[str, Any]: 比较结果
        """
        comparison_results = []

        for i, method_options in enumerate(methods_list):
            result = self.process_query(query, method_options)
            comparison_results.append({
                'method_index': i,
                'options': method_options,
                'result': result,
                'metrics': self._calculate_method_metrics(result)
            })

        # 找出最佳方法
        best_method = max(comparison_results, key=lambda x: x['metrics']['overall_score'])

        return {
            'query': query,
            'comparison_results': comparison_results,
            'best_method': best_method,
            'recommendation': self._generate_method_recommendation(comparison_results)
        }

    def _calculate_method_metrics(self, result: QueryProcessResult) -> Dict[str, float]:
        """计算处理方法指标"""
        metrics = {
            'processing_time': result.processing_time,
            'keyword_quality': len(result.keywords) / 10,  # 简化：关键词数量
            'expansion_effectiveness': 0,
            'overall_score': 0
        }

        # 扩展有效性
        if result.metadata.get('expansion_info'):
            expansion_ratio = result.metadata['expansion_info'].get('expansion_ratio', 0)
            metrics['expansion_effectiveness'] = min(expansion_ratio, 1.0)

        # 综合得分（可根据需要调整权重）
        metrics['overall_score'] = (
            metrics['keyword_quality'] * 0.4 +
            metrics['expansion_effectiveness'] * 0.4 +
            (1 - min(metrics['processing_time'], 1.0)) * 0.2  # 处理时间越短得分越高
        )

        return metrics

    def _generate_method_recommendation(self, comparison_results: List[Dict]) -> str:
        """生成方法推荐"""
        if not comparison_results:
            return "无法生成推荐：没有比较结果"

        best = comparison_results[0]
        for result in comparison_results[1:]:
            if result['metrics']['overall_score'] > best['metrics']['overall_score']:
                best = result

        options = best['options']
        recommendations = []

        if options['enable_expansion']:
            recommendations.append("启用查询扩展")
        if options['max_keywords'] > 10:
            recommendations.append("增加关键词数量")
        if 'synonyms' in options.get('expansion_methods', []):
            recommendations.append("使用同义词扩展")

        if recommendations:
            return f"推荐方法: {', '.join(recommendations)}"
        else:
            return "使用默认处理方法"

    def get_processing_stats(self, queries: List[str]) -> Dict[str, Any]:
        """
        获取处理统计信息

        Args:
            queries: 查询列表

        Returns:
            Dict[str, Any]: 统计信息
        """
        if not queries:
            return {
                'total_queries': 0,
                'avg_processing_time': 0,
                'avg_keyword_count': 0,
                'expansion_usage_rate': 0
            }

        results = self.process_query_batch(queries)

        total_time = sum(r.processing_time for r in results)
        total_keywords = sum(len(r.keywords) for r in results)
        expansion_count = sum(1 for r in results if r.expanded_query != r.cleaned_query)

        return {
            'total_queries': len(queries),
            'avg_processing_time': total_time / len(results),
            'avg_keyword_count': total_keywords / len(results),
            'expansion_usage_rate': expansion_count / len(results),
            'success_rate': sum(1 for r in results if not r.metadata.get('error')) / len(results),
            'processing_details': {
                'avg_original_length': sum(len(r.original_query) for r in results) / len(results),
                'avg_cleaned_length': sum(len(r.cleaned_query) for r in results) / len(results),
                'avg_expanded_length': sum(len(r.expanded_query) for r in results) / len(results)
            }
        }

    def optimize_for_domain(self, domain: str) -> Dict[str, Any]:
        """
        为特定领域优化处理配置

        Args:
            domain: 领域名称

        Returns:
            Dict[str, Any]: 优化后的配置
        """
        domain_configs = {
            'technical': {
                'options': {
                    'keyword_method': 'frequency',
                    'enable_expansion': True,
                    'expansion_methods': ['synonyms'],
                    'max_keywords': 12,
                    'max_expansions': 6
                }
            },
            'academic': {
                'options': {
                    'keyword_method': 'hybrid',
                    'enable_expansion': True,
                    'expansion_methods': ['synonyms', 'related'],
                    'max_keywords': 15,
                    'max_expansions': 8
                }
            },
            'general': {
                'options': {
                    'keyword_method': 'hybrid',
                    'enable_expansion': False,
                    'max_keywords': 8,
                    'max_expansions': 5
                }
            },
            'search': {
                'options': {
                    'keyword_method': 'frequency',
                    'enable_expansion': True,
                    'expansion_methods': ['related'],
                    'max_keywords': 10,
                    'max_expansions': 5
                }
            }
        }

        config = domain_configs.get(domain, domain_configs['general'])

        print(f"已为 '{domain}' 领域优化处理配置")
        return config

    def __str__(self) -> str:
        """返回处理器信息的字符串表示"""
        stats = self.get_dictionary_stats()
        return f"""
=== 查询处理器配置 ===
清理功能: 启用
关键词提取: 启用 ({self.keyword_extractor.use_jieba and 'jieba分词' or '简单分词'})
查询扩展: 启用
默认关键词方法: {self.default_options['keyword_method']}
默认最大关键词数: {self.default_options['max_keywords']}
默认最大扩展数: {self.default_options['max_expansions']}
        """.strip()

    def get_dictionary_stats(self) -> Dict[str, Any]:
        """获取词典统计信息"""
        return self.expander.get_dictionary_stats()


# 全局查询处理器实例
query_processor = QueryProcessor()